package com.boruan.shengtangfeng.admin.config;

import com.boruan.shengtangfeng.admin.jwt.filter.CustomLogoutSuccessHandler;
import com.boruan.shengtangfeng.admin.jwt.filter.JWTLoginFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import com.boruan.shengtangfeng.admin.jwt.UserAuthenticationProvider;
import com.boruan.shengtangfeng.admin.jwt.exception.JwtAuthenticationEntryPoint;
import com.boruan.shengtangfeng.admin.jwt.filter.JWTAuthenticationFilter;
import com.boruan.shengtangfeng.admin.jwt.handler.LoginFailureHandler;

/**
 * SpringSecurity的配置
 * 通过SpringSecurity的配置，将JWTLoginFilter，JWTAuthenticationFilter组合在一起
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

	@Value("${jwt.exceptUrl}")
	private String exceptUrl;

	@Autowired
	private JwtAuthenticationEntryPoint unauthorizedHandler;

	@Autowired
	private UserAuthenticationProvider userAuthenticationProvider;

	@Bean
	public JWTAuthenticationFilter authenticationTokenFilterBean() throws Exception {
		return new JWTAuthenticationFilter(authenticationManager(), unauthorizedHandler);
	}

	@Bean
	public JWTLoginFilter loginFilterBean() throws Exception {
		JWTLoginFilter jwtLoginFilter = new JWTLoginFilter(authenticationManager());
		// 只有登录的时候才去走过滤器
		jwtLoginFilter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/api/login"));
		jwtLoginFilter.setAuthenticationFailureHandler(loginFailureHandler());
		return jwtLoginFilter;
	}

	@Bean
	public LoginFailureHandler loginFailureHandler() {
		return new LoginFailureHandler();
	}

	@Bean
	public CustomLogoutSuccessHandler customLogoutSuccessHandlerBean() throws Exception {
		return new CustomLogoutSuccessHandler();
	}

	// 设置 HTTP 验证规则
	@Override
	protected void configure(HttpSecurity http) throws Exception {

		http.cors().and().csrf().disable() // 登录失败
				.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()// 未授权处理
				.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()
				// 所有 /users/signup 的POST请求 都放行
				// 注册方法用到的请求需要放行
				.anyRequest().authenticated() // 所有请求需要身份认证
				.and().addFilter(loginFilterBean()).addFilter(authenticationTokenFilterBean()).logout()
				.logoutSuccessHandler(customLogoutSuccessHandlerBean()) // 默认注销行为为logout，可以通过下面的方式来修改
				.logoutUrl("/logout")
//            .logoutSuccessUrl("/login")
				.permitAll();// 设置注销成功后跳转页面，默认是跳转到登录页面;
	}

	@Override
	public void configure(WebSecurity web) {
		web.ignoring().antMatchers(HttpMethod.POST, exceptUrl)
    	   .antMatchers("/admin/login/passwordLogin") // 微信登录
		   .antMatchers("/admin/login/**") // 微信登录
//    	   .antMatchers("/api/changePassword") //忘记密码
//    	   .antMatchers("/api/verficationCode/**") //验证码
				.antMatchers("/admin/oss/ueditor") //上传图片
				.antMatchers("/aliyun/oss/**") //上传图片
				.antMatchers("/swagger-ui.html").antMatchers("/swagger-resources/**").antMatchers("/images/**")
				.antMatchers("/webjars/**").antMatchers("/v2/api-docs").antMatchers("/configuration/ui")
				.antMatchers("/configuration/security").antMatchers("/error");
	}

	@Override
	public void configure(AuthenticationManagerBuilder auth) throws Exception {
		// 使用自定义身份验证组件
		auth.authenticationProvider(userAuthenticationProvider);
	}

}
